/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.objectbrowser;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.infobus.*;
import org.openide.awt.Toolbar;
import org.openide.awt.ToolbarToggleButton;
import org.openide.awt.ToolbarButton;
import org.openide.explorer.ExplorerActions;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerManager.Provider;
import org.openide.nodes.*;
import org.openide.windows.TopComponent;
/**
* Encapsulation of Explorer views. This bean has property explorerViewClassName which
* define the type of explorer view. ExplorerBean adds to Explorer views special functionality
* used in Object Browser like communication with other ExplorerBeans and setting filter.
*
* @author Jan Jancura
*/
public class ExplorerBean extends JPanel implements InfoBusMember,
InfoBusDataConsumer, InfoBusDataProducer, Provider {
// static ............................................................................
public static final String PROPERTY_EXPLORER_VIEW_CLASS_NAME = "explorerViewClassName"; // NOI18N
/** Icons for buttons. */
static protected Icon iFirst;
static protected Icon iSecond;
static protected Icon iThird;
static protected Icon iFourth;
static ExplorerActions explorerActions = new ExplorerActions ();
static {
try {
iFirst = new ImageIcon (ExplorerBean.class.getResource ("/org/netbeans/modules/objectbrowser/resources/package.gif")); // NOI18N
iSecond = new ImageIcon (ExplorerBean.class.getResource ("/org/netbeans/modules/objectbrowser/resources/class.gif")); // NOI18N
iThird = new ImageIcon (ExplorerBean.class.getResource ("/org/netbeans/modules/objectbrowser/resources/interface.gif")); // NOI18N
iFourth = new ImageIcon (ExplorerBean.class.getResource ("/org/netbeans/modules/objectbrowser/resources/variable.gif")); // NOI18N
} catch (Throwable w) {
w.printStackTrace ();
}
}
static Component findFocusable (Container c) {
int i, k = c.getComponentCount ();
Component cc;
for (i = 0; i < k; i++)
if ((cc = c.getComponent (i)).isFocusTraversable ())
return cc;
else
if (cc instanceof Container) return findFocusable ((Container) cc);
return null;
}
// variables ............................................................................
// property variables
private String infoBusName = HierarchyTranslator.PROPERTY_DEFAULT_INFO_BUS_NAME;
private String inputName;
private String outputName;
private String title;
private boolean toolbarVisible;
private transient PropertyChangeSupport pcs;
// InfoBus support
private transient InfoBusMemberSupport ibms;
private boolean connected = false;
private boolean designTime = false;
private transient HierarchyTranslator translator;
// Explorer support
private transient ExplorerManager explorerManager;
private Component explorerView;
private PropertyChangeListener explorerListener;
private TopComponent topComponent;
// current state encaps.
private boolean[] filter = new boolean [0];
private HierarchyTranslator.Filter subFilter;
private FilterListener filterListener = new FilterListener ();
private Node[] rootNodes;
private boolean isFacused = false;
// init .................................................................................
static final long serialVersionUID =-5840264857341760916L;
public ExplorerBean() {
setLayout (new BorderLayout ());
setBorder (new CompoundBorder (
new LineBorder (getBackground ()),
new org.netbeans.modules.objectbrowser.BevelBorder (EtchedBorder.LOWERED)
));
rootNodes = null;
init ();
try {
setExplorerViewClassName ("org.openide.explorer.view.BeanTreeView"); // NOI18N
} catch (PropertyVetoException e) {
}
}
protected void init () {
pcs = new PropertyChangeSupport (this);
ibms = new InfoBusMemberSupport (this);
explorerManager = new ExplorerManager ();
explorerManager.addPropertyChangeListener (explorerListener =
new PropertyChangeListener () {
public void propertyChange (PropertyChangeEvent e) {
// fire selection changes
if ( (outputName != null) && (e.getPropertyName () != null) && connected &&
e.getPropertyName ().equals (ExplorerManager.PROP_SELECTED_NODES)
) {
ibms.getInfoBus ().fireItemAvailable (outputName, null, ExplorerBean.this);
}
if ((topComponent != null) && isFacused) {
topComponent.setActivatedNodes (explorerManager.getSelectedNodes ());
}
}
}
);
if (!designTime)
connect ();
}
// properties ...........................................................................
public String getExplorerViewClassName () {
if (explorerView == null) return "none"; // NOI18N
return explorerView.getClass ().getName ();
}
public void setExplorerViewClassName (String name) throws PropertyVetoException {
// create new view
Class c;
try {
c = Class.forName (name);
} catch (ClassNotFoundException e) {
throw new PropertyVetoException (
name + " ClassNotFoundException occurred while creating ExplorerView.", // NOI18N
new PropertyChangeEvent (
this,
PROPERTY_EXPLORER_VIEW_CLASS_NAME,
getExplorerViewClassName (),
name
)
);
}
Constructor cc;
try {
cc = c.getConstructor (new Class [] {}); //1 ExplorerManager.class});
} catch (Exception e) {
throw new InternalError ();
}
Object o;
try {
o = cc.newInstance (new Object [] {});
} catch (InstantiationException e) {
throw new PropertyVetoException (
"InstantiationException occurred while creating ExplorerView.", // NOI18N
new PropertyChangeEvent (
this,
PROPERTY_EXPLORER_VIEW_CLASS_NAME,
getExplorerViewClassName (),
name
)
);
} catch (java.lang.reflect.InvocationTargetException e) {
e.getTargetException ().printStackTrace ();
throw new PropertyVetoException (
"java.lang.reflect.InvocationTargetException occurred while creating ExplorerView.", // NOI18N
new PropertyChangeEvent (
this,
PROPERTY_EXPLORER_VIEW_CLASS_NAME,
getExplorerViewClassName (),
name
)
);
} catch (IllegalAccessException e) {
throw new PropertyVetoException (
"IllegalAccessException occurred while creating ExplorerView.", // NOI18N
new PropertyChangeEvent (
this,
PROPERTY_EXPLORER_VIEW_CLASS_NAME,
getExplorerViewClassName (),
name
)
);
}
// PENDING explorerView.deinitialize ();
explorerView = (Component)o;
// customize view
if (explorerView instanceof JComponent)
((JComponent) explorerView).setBorder (new EtchedBorder (EtchedBorder.LOWERED));
if (explorerView instanceof org.openide.explorer.view.ListView) {
((org.openide.explorer.view.ListView) explorerView).setTraversalAllowed (false);
}
if (explorerView instanceof org.openide.explorer.view.TreeView) {
((org.openide.explorer.view.TreeView) explorerView).setRootVisible (false);
}
Component f = findFocusable ((Container) explorerView);
f.addFocusListener (new FocusAdapter () {
public void focusGained (FocusEvent e) {
if (topComponent != null) {
topComponent.setActivatedNodes (explorerManager.getSelectedNodes ());
}
explorerActions.attach (explorerManager);
setBorder (new CompoundBorder (
new LineBorder (Color.black),
new BevelBorder (EtchedBorder.LOWERED)
));
isFacused = true;
}
public void focusLost (FocusEvent e) {
setBorder (new CompoundBorder (
new LineBorder (getBackground ()),
new BevelBorder (EtchedBorder.LOWERED)
));
isFacused = false;
// explorerActions.detach ();
}
});
// empty nodes
explorerManager.removePropertyChangeListener (explorerListener);
explorerManager = new ExplorerManager ();
explorerManager.addPropertyChangeListener (explorerListener);
// change view
repaintView ();
// empty nodes
refreshNodes ();
}
public String getInputName () {
return inputName;
}
public void setInputName (String name) {
String old = inputName;
inputName = name;
pcs.firePropertyChange ("inputName", old, inputName); // NOI18N
}
public String getOutputName () {
return outputName;
}
public void setOutputName (String name) {
String old = outputName;
outputName = name;
pcs.firePropertyChange ("outputName", old, outputName); // NOI18N
}
public String getInfoBusName () {
return infoBusName;
}
public void setInfoBusName (String name) throws PropertyVetoException {
String old = infoBusName;
disconnect ();
infoBusName = name;
connect ();
pcs.firePropertyChange ("infoBusName", old, infoBusName); // NOI18N
}
public String getTitle () {
return title;
}
public void setTitle (String title) {
String old = title;
this.title = title;
pcs.firePropertyChange ("title", old, title); // NOI18N
repaintView ();
}
public boolean getToolbarVisible () {
return toolbarVisible;
}
public void setToolbarVisible (boolean b) {
boolean old = b;
toolbarVisible = b;
pcs.firePropertyChange ("toolbarVisible", new Boolean (old), new Boolean (toolbarVisible)); // NOI18N
repaintView ();
}
public FilterSettings getFilterSettings () {
String[] n = null;
String[] h = null;
if (translator != null) {
n = translator.getFilterNames ();
h = translator.getFilterComments ();
}
return new FilterSettings (filter, n, h);
}
public void setFilterSettings (FilterSettings fs) {
filter = fs.getFilter ();
repaintView ();
refreshNodes ();
}
// helper methods .................................................................
public void addNotify () {
if (designTime) connect ();
topComponent = (TopComponent) SwingUtilities.getAncestorOfClass (TopComponent.class, this);
super.addNotify ();
}
public void removeNotify () {
if (designTime) disconnect ();
topComponent = (TopComponent) SwingUtilities.getAncestorOfClass (TopComponent.class, this);
super.removeNotify ();
}
void expandAll () {
((org.openide.explorer.view.TreeView) explorerView).expandAll ();
}
/**
* Creates visual rep.
* title + toolbarVisible + subFilter => repaint
*/
private void repaintView () {
if (explorerView == null) return;
removeAll ();
JComponent inn = this;
if (title != null) {
JLabel l = new JLabel (title, SwingConstants.CENTER);
l.setBorder (new EtchedBorder (EtchedBorder.LOWERED));
add (l, "North"); // NOI18N
inn = new JPanel (new BorderLayout ());
add (inn, "Center"); // NOI18N
}
if (toolbarVisible) {
Component c = null;
if (subFilter != null) c = subFilter.getComponent ();
if (c == null) {
JPanel j = new JPanel ();
j.setBorder (new EtchedBorder (EtchedBorder.LOWERED));
inn.add (j, "North"); // NOI18N
} else
inn.add (c, "North"); // NOI18N
}
inn.add (explorerView, "Center"); // NOI18N
validate ();
}
private void setTranslator () {
Object old = translator;
translator = (HierarchyTranslator) ibms.getInfoBus ().findDataItem (
HierarchyTranslator.PROPERTY_DEFAULT_TRANSLATOR_ITEM_NAME,
null,
this
);
if (old == translator) return;
/*
S ystem.out.println ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
S ystem.out.println ("ExplorerBean.setNewTranslator: " + translator + " old: " + old);
T hread.dumpStack ();
S ystem.out.println ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
*/
if (translator != null) {
int i, k = translator.getFilterNames ().length;
if (k != filter.length) {
filter = new boolean [k];
for (i = 0; i < k; i++)
filter [i] = true;
}
}
refreshNodes ();
repaintView ();
}
/**
* Updates sub filter.
* called from refreshNodes () only
*/
private void setSubFilter (HierarchyTranslator.Filter f) {
if ( (subFilter != null) &&
subFilter.getClass ().equals (f.getClass ())
) return;
if (subFilter != null) subFilter.removePropertyChangeListener (filterListener);
f.addPropertyChangeListener (filterListener);
subFilter = f;
}
/**
* Updates sub filter & nodes.
* rootNodes => explorerManager, setSubFilter ()
*/
private void refreshNodes () {
if (translator != null) {
setSubFilter (translator.getFilter (rootNodes, filter, this));
SwingUtilities.invokeLater (new Runnable () {
public void run () {
Node nnn = translator.translate (rootNodes, filter, subFilter); //S ystem.out.println ("Explorer bean - setRoot " + nnn); // NOI18N
//Thread.dumpStack ();
explorerManager.setRootContext (nnn);
try {
explorerManager.setSelectedNodes (new Node[] {});
} catch (PropertyVetoException e) {
}
}
});
} else
if (rootNodes == null) { //S ystem.out.println ("Explorer bean - set empty root"); // NOI18N
explorerManager.setRootContext (new AbstractNode (Children.LEAF));
try {
explorerManager.setSelectedNodes (new Node[] {});
} catch (PropertyVetoException e) {
}
} else { //S ystem.out.println ("Explorer bean - set special root"); // NOI18N
explorerManager.setRootContext (
new AbstractNode (new Children.Array () {
protected Node[] createNodes () {
int i, k = rootNodes.length;
Node[] nn = new Node [k];
for (i = 0; i < k; i++)
nn [i] = rootNodes [i].cloneNode ();
return nn;
}
public String toString () {
return "ExplorerBean.Full node " + title + "[" + super.toString () + "]"; // NOI18N
}
})
);
try {
explorerManager.setSelectedNodes (new Node[] {});
} catch (PropertyVetoException e) {
}
}
}
/** Get the explorer manager.
* @return the manager
*/
public ExplorerManager getExplorerManager () {
return explorerManager;
}
public String toString () {
if (title != null) return "ExplorerBean " + title; // NOI18N
return super.toString ();
}
// InfoBus support .................................................................
private void connect () {
if (connected) return;
try {
ibms.joinInfoBus (infoBusName);
} catch (InfoBusMembershipException e) {
throw new InternalError ();
} catch (PropertyVetoException e) {
throw new InternalError ();
}
ibms.getInfoBus ().addDataConsumer (this);
setTranslator ();
if (outputName != null) ibms.getInfoBus ().addDataProducer (this);
connected = true;
}
private void disconnect () {
if (!connected) return;
if (ibms.getInfoBus () == null) return;
ibms.getInfoBus ().removeDataConsumer (this);
ibms.getInfoBus ().removeDataProducer (this);
try {
ibms.leaveInfoBus ();
} catch (InfoBusMembershipException e) {
throw new InternalError ();
} catch (PropertyVetoException e) {
throw new InternalError ();
}
setTranslator ();
connected = false;
}
public void setInfoBus (InfoBus newInfoBus) throws PropertyVetoException {
ibms.setInfoBus (newInfoBus);
}
public InfoBus getInfoBus () {
return ibms.getInfoBus ();
}
public void addInfoBusVetoableListener (VetoableChangeListener vcl) {
ibms.addInfoBusVetoableListener (vcl);
}
public void removeInfoBusVetoableListener (VetoableChangeListener vcl) {
ibms.removeInfoBusVetoableListener (vcl);
}
public void addInfoBusPropertyListener (PropertyChangeListener pcl) {
ibms.addInfoBusPropertyListener (pcl);
}
public void removeInfoBusPropertyListener (PropertyChangeListener pcl) {
ibms.removeInfoBusPropertyListener (pcl);
}
public void dataItemAvailable (InfoBusItemAvailableEvent e) {
if (e.getDataItemName ().equals (HierarchyTranslator.PROPERTY_DEFAULT_TRANSLATOR_ITEM_NAME)) {
setTranslator ();
return;
}
if (inputName == null) return;
if (!e.getDataItemName ().equals (inputName)) return;
rootNodes = (Node[]) e.requestDataItem (this, null);
refreshNodes ();
}
public void dataItemRevoked (InfoBusItemRevokedEvent e) {
if (e.getDataItemName ().equals (HierarchyTranslator.PROPERTY_DEFAULT_TRANSLATOR_ITEM_NAME))
setTranslator ();
}
public void propertyChange (PropertyChangeEvent e) {
}
public void dataItemRequested (InfoBusItemRequestedEvent e) {
if ((outputName != null) && e.getDataItemName ().equals (outputName)) { //S ystem.out.println("ExplorerBean.ItemRequested " + title + " : " + explorerManager.getSelectedNodes ().length); // NOI18N
e.setDataItem (explorerManager.getSelectedNodes ());
}
}
// innerclasses .........................................................................
public static class FilterSettings implements Serializable {
static final long serialVersionUID = 8392364514965433706L;
private boolean[] filter;
private String[] names;
private String[] hints;
public FilterSettings (boolean[] fs) {
filter = fs;
}
public FilterSettings (boolean[] fs, String[] n, String[] h) {
filter = fs;
names = n;
hints = h;
}
String[] getFilterNames () {
return names;
}
String[] getFilterComments () {
return hints;
}
FilterSettings forFilter (boolean[] b) {
FilterSettings fs = new FilterSettings (b);
fs.names = names;
fs.hints = hints;
return fs;
}
boolean[] getFilter () {
return filter;
}
}
class FilterListener implements PropertyChangeListener {
public void propertyChange (PropertyChangeEvent e) {
SwingUtilities.invokeLater (new Runnable () {
public void run () {
Node n = translator.translate (rootNodes, filter, subFilter); //S ystem.out.println ("Explorer bean - change filter " + n); // NOI18N
explorerManager.setRootContext (new AbstractNode (Children.LEAF));
explorerManager.setRootContext (n);
}
});
}
}
}
/*
* Log
* 21 src-jtulach1.20 1/13/00 Radko Najman I18N
* 20 src-jtulach1.19 12/15/99 Jan Jancura
* 19 src-jtulach1.18 12/15/99 Jan Jancura Bug 4012
* 18 src-jtulach1.17 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems copyright in file comment
* 17 src-jtulach1.16 10/4/99 Jan Jancura Bug 2783
* 16 src-jtulach1.15 8/19/99 Jan Jancura Bug 3434
* 15 src-jtulach1.14 8/9/99 Ian Formanek Generated Serial Version
* UID
* 14 src-jtulach1.13 7/27/99 Jan Jancura
* 13 src-jtulach1.12 7/2/99 Jan Jancura
* 12 src-jtulach1.11 6/9/99 Ian Formanek ---- Package Change To
* org.openide ----
* 11 src-jtulach1.10 5/17/99 Jan Jancura Bug 1535, 1765
* 10 src-jtulach1.9 5/12/99 Jan Jancura
* 9 src-jtulach1.8 5/6/99 Jan Jancura
* 8 src-jtulach1.7 4/26/99 Jan Jancura
* 7 src-jtulach1.6 4/16/99 Jan Jancura
* 6 src-jtulach1.5 4/9/99 Jan Jancura Bug 1508
* 5 src-jtulach1.4 4/8/99 Jan Jancura
* 4 src-jtulach1.3 4/6/99 Ian Formanek fixed obtaining
* resources (Object.class.getResource -> getClass ().getResource)
* 3 src-jtulach1.2 4/2/99 Jan Jancura
* 2 src-jtulach1.1 3/23/99 Jan Jancura
* 1 src-jtulach1.0 3/23/99 Jan Jancura
* $
*/